﻿using System;
using System.Globalization;

using zijian666.Converts.Extensions;

namespace zijian666.Converts.Core;

/// <summary>
/// 异常帮助类
/// </summary>
internal static class ExceptionHelper
{
    /// <summary>
    /// 获取转换失败描述
    /// </summary>
    /// <typeparam name="T">输入类型</typeparam>
    /// <param name="input">输入值</param>
    /// <param name="typeName">输出类型名称</param>
    /// <param name="cultureInfo">区域信息</param>
    /// <returns></returns>
    public static string ConvertFailMessage<T>(T input, string typeName, CultureInfo? cultureInfo)
    {
        if (string.IsNullOrWhiteSpace(typeName))
        {
            throw new ArgumentException($"“{nameof(typeName)}”不能为 null 或空白。", nameof(typeName));
        }

        var rs = ResourceStringManager.GetResource(cultureInfo);
        var text = (input as IConvertible)?.ToString(null)
                  ?? (input as IFormattable)?.ToString(null, null);
        if (input is null)
        {
            return string.Format(rs.CANT_CONVERT, "null", "null", typeName);
        }
        var inputType = typeof(T) == typeof(object) ? input.GetType() : typeof(T);
        if (text is null)
        {
            return string.Format(rs.CANT_CONVERT, "", inputType.GetFriendlyName(), typeName);
        }
        return string.Format(rs.CANT_CONVERT, text, inputType.GetFriendlyName(), typeName);
    }

    /// <summary>
    /// 无法创建转换器异常
    /// </summary>
    /// <param name="typeName">输出类型名称</param>
    /// <param name="reason">原因</param>
    /// <param name="cultureInfo">区域信息</param>
    /// <returns></returns>
    /// <exception cref="NotSupportedException">无法生成 <paramref name="typeName"/> 类型的转换器：<paramref name="reason"/></exception>
    public static NotSupportedException CantBuildConvertor(string typeName, string reason, CultureInfo? cultureInfo)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        return new NotSupportedException(string.Format(rs.CANT_BUILD_CONVERTOR, typeName, rs[reason]));
    }
    /// <summary>
    /// 转换失败异常
    /// </summary>
    /// <typeparam name="T">输入类型</typeparam>
    /// <param name="input">输入值</param>
    /// <param name="typeName">输出类型名称</param>
    /// <param name="cultureInfo">区域信息</param>
    /// <param name="e">转换失败的异常</param>
    /// <returns></returns>
    public static InvalidCastException ConvertFail<T>(T input, string typeName, CultureInfo? cultureInfo, Exception? e)
    {
        var message = ConvertFailMessage(input, typeName, cultureInfo);
        return new InvalidCastException(message, e);
    }
    /// <summary>
    /// 值范围溢出异常
    /// </summary>
    /// <param name="message">异常描述</param>
    /// <param name="cultureInfo">区域信息</param>
    /// <param name="exception">内部异常</param>
    /// <returns></returns>
    public static OverflowException Overflow(string message, CultureInfo? cultureInfo, Exception? exception = null)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        return new OverflowException(string.Format(rs.VALUE_OVERFLOW, message), exception);
    }

    /// <summary>
    /// <paramref name="typeName"/> 无法创建对象实例
    /// </summary>
    public static InvalidCastException InstantiationFail(string typeName, CultureInfo? cultureInfo, Exception? exception = null)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        var message = string.Format(rs.INSTANTIATION_FAIL, typeName);
        return new InvalidCastException(message, exception);
    }

    /// <summary>
    /// <paramref name="typeName"/> 属性名 转换失败: <paramref name="propertyName"/>
    /// </summary>
    public static InvalidCastException PropertyCastFail(string typeName, string propertyName, CultureInfo? cultureInfo, Exception? exception)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        var message = string.Format(rs.PROPERTY_CAST_FAIL, typeName, propertyName);
        return new InvalidCastException(message, exception);
    }
    /// <summary>
    /// <paramref name="typeName"/> 属性 <paramref name="propertyName"/> 设置失败，值：<paramref name="value"/>
    /// </summary>
    public static InvalidCastException PropertySetFail(string typeName, string propertyName, object? value, CultureInfo? cultureInfo, Exception? exception)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        var message = string.Format(rs.PROPERTY_SET_FAIL, typeName, propertyName, value);
        return new InvalidCastException(message, exception);
    }

    /// <summary>
    /// 集合 <paramref name="typeName"/> 键 <paramref name="key"/> 转换失败
    /// </summary>
    public static InvalidCastException CollectionKeyFail(string typeName, string key, CultureInfo? cultureInfo, Exception? exception)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        var message = string.Format(rs.COLLECTION_KEY_FAIL, typeName, key);
        return new InvalidCastException(message, exception);
    }

    /// <summary>
    /// 集合 <paramref name="typeName"/> 插值失败，[<paramref name="key"/>]=<paramref name="value"/>
    /// </summary>
    public static InvalidCastException CollectionAddFail(string typeName, string key, object? value, CultureInfo? cultureInfo, Exception? exception)
    {
        var rs = ResourceStringManager.GetResource(cultureInfo);
        var message = string.Format(rs.COLLECTION_ADD_FAIL, typeName, key, value);
        return new InvalidCastException(message, exception);
    }
}